/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.simpleini;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author waigore
 */
public class Ini {
    private static final String ROOT = "!~!~@~!@@~#ROOT@!@#!@";

    private Map< String, Map <String, String> > sections;

    public Ini()
    {
        sections = new HashMap();
        sections.put(ROOT, new HashMap());
    }

    public Ini loadFrom(FileInputStream fis) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
        String line = null, sectionName;
        Map<String, String> currSection = sections.get(ROOT);

        while ((line = reader.readLine()) != null)
        {
            if (line.startsWith(";") || line.startsWith("#"))
            {
                continue;
            }
            line = line.trim();

            if (line.startsWith("[") && line.endsWith("]")) {
                sectionName = line.substring(1, line.length() - 1);
                currSection = new HashMap();
                sections.put(sectionName, currSection);

            } else if (line.contains("=")) {
                String[] elements = line.split("=");
                if (elements.length == 1) {
                    currSection.put(elements[0].trim(), "");
                } else {
                    currSection.put(elements[0].trim(), elements[1]);
                }
            }
            else
            {
                //we treat this as an empty line
            }

        }

        reader.close();

        return this;
    }

    public void saveTo(FileOutputStream fos) throws IOException
    {
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos));

        /* Write the root section first */
        Map<String, String> rootSection = sections.get(ROOT);
        if (!rootSection.isEmpty())
        {
            writeln(writer, ";; ROOT SECTION ;;");
            writeSection(writer, rootSection);
            writeln(writer, "");
        }

        for (String sectionName: sections.keySet())
        {
            if (sectionName.equals(ROOT))
            {
                continue;
            }

            Map<String, String> section = sections.get(sectionName);
            writeln(writer, String.format("[%s]", sectionName));
            writeSection(writer, section);
            writeln(writer, "");

        }

        writer.close();
    }

    private void writeln(BufferedWriter writer, String line) throws IOException
    {
        writer.write(String.format("%s\n", line));
    }

    private void writeSection(BufferedWriter writer, Map<String, String> section) throws IOException
    {
        for (String key: section.keySet())
        {
            writeln(writer, String.format("%s=%s", key, section.get(key)));
        }
    }

    public Ini putInt(String sectionName, String keyName, int value)
    {
        return putString(sectionName, keyName, String.format("%d", value));
    }

    public int getInt(String sectionName, String keyName, int defValue)
    {
        String value = getString(sectionName, keyName);
        if (value == null)
        {
            return defValue;
        }
        else
        {
            return Integer.parseInt(value);
        }
    }

    public Ini putLong(String sectionName, String keyName, long value)
    {
        return putString(sectionName, keyName, String.format("%d", value));
    }

    public long getLong(String sectionName, String keyName, long defValue)
    {
        String value = getString(sectionName, keyName);
        if (value == null)
        {
            return defValue;
        }
        else
        {
            return Long.parseLong(value);
        }
    }

    public Ini putRootString(String keyName, String value)
    {
        return putString(ROOT, keyName, value);
    }

    public Ini putString(String sectionName, String keyName, String value)
    {
        Map<String, String> section = sections.get(sectionName);
        if (section == null)
        {
            section = new HashMap();
            sections.put(sectionName, section);
        }
        if (value == null)
        {
            section.remove(keyName);
        }
        else
        {
            section.put(keyName, value);
        }
        

        return this;
    }

    public String getRootString(String keyName)
    {
        return getString(ROOT, keyName, null);
    }

    public String getRootString(String keyName, String defValue)
    {
        return getString(ROOT, keyName, defValue);
    }

    public String getString(String sectionName, String keyName)
    {
        return getString(sectionName, keyName, null);
    }
    
    public String getString(String sectionName, String keyName, String defValue)
    {
        Map<String, String> section = sections.get(sectionName);
        if (section == null)
        {
            return defValue;
        }

        String value = section.get(keyName);
        if (value == null)
        {
            return defValue;
        }
        else
        {
            return value;
        }
    }

    public Map<String, String> getSection(String sectionName)
    {
        Map<String, String> section = sections.get(sectionName);
        if (section == null)
        {
            section = new HashMap();
            sections.put(sectionName, section);
        }
        return section;
    }

    public boolean removeSection(String sectionName)
    {
        Map<String, String> section = sections.get(sectionName);
        if (section == null)
        {
            return false;
        }

        sections.remove(sectionName);
        return true;
    }
}
